package gu.simplemq;

import java.lang.reflect.ParameterizedType;

import gu.simplemq.pool.BaseMQInstance;
import gu.simplemq.pool.BaseMQPool;
import gu.simplemq.utils.LifoShutdownHooks;

/**
 * 消息对象抽象工厂类，用于管理producer/consumer,publisher/subscriber等类型的消息处理对象<br>
 * 应用程序结束时会自动清除所有producer/consumer和publisher/subscriber
 * 
 * @author guyadong
 *
 * @param <CON>  {@link IConsumer}实现类
 * @param <PRD>  {@link IProducer}实现类
 * @param <SUB>  {@link ISubscriber}实现类
 * @param <PUB>  {@link IConsumer}实现类
 * @param <POOL> {@link BaseMQPool}实现类
 * @author guyadong
 * @since 2.4.0
 */
@SuppressWarnings("rawtypes")
public class MQInstanceFactory<CON extends IConsumer, PRD extends IProducer, SUB extends ISubscriber, PUB extends IPublisher, POOL extends BaseMQPool>
		implements MQInstanceSupplier<POOL> {
	private final BaseMQInstance<CON, POOL> CONSUMERS;
	private final BaseMQInstance<PRD, POOL> PRODUCERS;
	private final BaseMQInstance<SUB, POOL> SUBSCRIBERS;
	private final BaseMQInstance<PUB, POOL> PUBLISHERS;

	/**
	 * 构造方法<br>
	 * 通过反射获取{@link IConsumer}、{@link IProducer}、{@link ISubscriber}、{@link IPublisher}、{@link BaseMQPool}的实现类
	 */
	protected MQInstanceFactory() {
		Class<CON> consumerClass = typeArgument(getClass(), 0);
		Class<PRD> producerClass = typeArgument(getClass(), 1);
		Class<SUB> subsciberClass = typeArgument(getClass(), 2);
		Class<PUB> publisherClass = typeArgument(getClass(), 3);
		Class<POOL> poolClass = typeArgument(getClass(), 4);
		CONSUMERS = new BaseMQInstance<>(consumerClass, poolClass);
		PRODUCERS = new BaseMQInstance<>(producerClass, poolClass);
		SUBSCRIBERS = new BaseMQInstance<>(subsciberClass, poolClass);
		PUBLISHERS = new BaseMQInstance<>(publisherClass, poolClass);
	}

	/**
	 * 构造方法
	 * 
	 * @param consumerClass  {@link IConsumer}实现类
	 * @param producerClass  {@link IProducer}实现类
	 * @param subsciberClass {@link ISubscriber}实现类
	 * @param publisherClass {@link IPublisher}实现类
	 * @param poolClass      {@link BaseMQPool}实现类
	 */
	public MQInstanceFactory(Class<CON> consumerClass, Class<PRD> producerClass, Class<SUB> subsciberClass,
			Class<PUB> publisherClass, Class<POOL> poolClass) {
		CONSUMERS = new BaseMQInstance<>(consumerClass, poolClass);
		PRODUCERS = new BaseMQInstance<>(producerClass, poolClass);
		SUBSCRIBERS = new BaseMQInstance<>(subsciberClass, poolClass);
		PUBLISHERS = new BaseMQInstance<>(publisherClass, poolClass);
	}

	/**
	 * 通过反射获取指定类型的泛型父类 ({@link Class#getGenericSuperclass()})
	 * 的类型参数({@link ParameterizedType})的第index个参数类型<br>
	 * 
	 * @param clazz
	 * @param index 第index个泛型参数类型
	 * @return
	 */
	@SuppressWarnings({ "unchecked" })
	private static <T> Class<T> typeArgument(Class clazz, int index) {
		return (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[index];
	}

	/**
	 * 从连接池返回对应的{@link IConsumer}实例
	 * 
	 * @param pool
	 * @see gu.simplemq.pool.BaseMQInstance#getInstance(Object)
	 */
	public CON getConsumer(POOL pool) {
		return CONSUMERS.getInstance(pool);
	}

	/**
	 * 从连接池返回对应的{@link IProducer}实例
	 * 
	 * @param pool
	 * @see gu.simplemq.pool.BaseMQInstance#getInstance(Object)
	 */
	public PRD getProducer(POOL pool) {
		return PRODUCERS.getInstance(pool);
	}

	/**
	 * 从连接池返回对应的{@link ISubscriber}实例
	 * 
	 * @param pool
	 * @see gu.simplemq.pool.BaseMQInstance#getInstance(Object)
	 */
	public SUB getSubscriber(POOL pool) {
		return SUBSCRIBERS.getInstance(pool);
	}

	/**
	 * 从连接池返回对应的{@link IPublisher}实例
	 * 
	 * @param pool
	 * @see gu.simplemq.pool.BaseMQInstance#getInstance(Object)
	 */
	public PUB getPublisher(POOL pool) {
		return PUBLISHERS.getInstance(pool);
	}

	/**
	 * 关闭并删除所有consumer,subscriber,producer
	 */
	public synchronized void closeAll() {
		CONSUMERS.clearInstances();
		PRODUCERS.clearInstances();
		SUBSCRIBERS.clearInstances();
		PUBLISHERS.clearInstances();
	}

	{
		// JVM 结束时自动清除所有consumer和subscriber,producer对象
		LifoShutdownHooks.addShutdownHook(toString(), new Runnable() {

			@Override
			public void run() {
				closeAll();
			}
		});
	}
}
